package com.insight.modules.ngalain.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.insight.common.util.oConvertUtils;
import com.insight.modules.ngalain.service.NgAlainService;
import com.insight.modules.system.entity.SysPermission;
import com.yuanqiao.insight.acore.system.mapper.SysDictMapper;
import com.insight.modules.system.service.ISysPermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Base64;
import java.util.List;
import java.util.Map;

@Service("ngAlainService")
@Transactional
public class NgAlainServiceImpl implements NgAlainService {

    @Autowired
    private ISysPermissionService sysPermissionService;

    @Autowired
    private SysDictMapper mapper;

    /**
     * 获取指定用户的菜单（入口方法）
     *
     * @param id 用户ID
     * @return 转换后符合NgAlain前端格式的菜单JSON数组
     * @throws Exception 可能的异常
     */
    @Override
    public JSONArray getMenu(String id){
        return getJeecgMenu(id);
    }

    /**
     * 根据用户ID查询权限，生成Jeecg格式菜单
     *
     * @param id 用户ID
     * @return Jeecg格式菜单JSON数组
     * @throws Exception 可能的异常
     */
    @Override
    public JSONArray getJeecgMenu(String id) {
        // 查询用户权限列表
        List<SysPermission> metaList = sysPermissionService.queryByUser(id);
        JSONArray jsonArray = new JSONArray();

        // 递归构建权限树结构的JSON数组
        getPermissionJsonArray(jsonArray, metaList, null);

        // 解析Jeecg权限JSON为NgAlain前端格式菜单
        JSONArray menulist = parseNgAlain(jsonArray);

        // 封装顶层菜单节点
        JSONObject jeecgMenu = new JSONObject();
        jeecgMenu.put("text", "jeecg菜单");
        jeecgMenu.put("group", true);
        jeecgMenu.put("children", menulist);

        JSONArray jeecgMenuList = new JSONArray();
        jeecgMenuList.add(jeecgMenu);
        return jeecgMenuList;
    }

    /**
     * 根据表名、键和值获取字典项，供前端展示下拉框等使用
     *
     * @param table 表名
     * @param key   键字段
     * @param value 值字段
     * @return 字典数据集合
     */
    @Override
    public List<Map<String, String>> getDictByTable(String table, String key, String value) {
        return this.mapper.getDictByTableNgAlain(table, key, value);
    }

    /**
     * 递归解析Jeecg权限JSON，转换为NgAlain菜单格式
     *
     * @param jsonArray Jeecg权限JSON数组
     * @return NgAlain菜单格式JSON数组
     */
    private JSONArray parseNgAlain(JSONArray jsonArray) {
        JSONArray menulist = new JSONArray();
        for (Object object : jsonArray) {
            JSONObject jsonObject = (JSONObject) object;
            String path = (String) jsonObject.get("path");
            JSONObject meta = (JSONObject) jsonObject.get("meta");

            JSONObject menu = new JSONObject();
            menu.put("text", meta.get("title"));
            menu.put("reuse", true);

            if (jsonObject.get("children") != null) {
                // 递归处理子菜单
                JSONArray child = parseNgAlain((JSONArray) jsonObject.get("children"));
                menu.put("children", child);

                // 设置图标属性
                JSONObject icon = new JSONObject();
                icon.put("type", "icon");
                icon.put("value", meta.get("icon"));
                menu.put("icon", icon);
            } else {
                // 叶子节点，设置链接地址
                menu.put("link", path);
            }
            menulist.add(menu);
        }
        return menulist;
    }

    /**
     * 递归构建权限JSON数组，生成层级结构
     *
     * @param jsonArray 结果存放数组
     * @param metaList  权限列表
     * @param parentJson 当前父节点JSON对象
     */
    private void getPermissionJsonArray(JSONArray jsonArray, List<SysPermission> metaList, JSONObject parentJson) {
        for (SysPermission permission : metaList) {
            if (permission.getMenuType() == null) {
                // 过滤菜单类型为空的权限
                continue;
            }
            String tempPid = permission.getParentId();

            // 根据权限生成对应的JSON对象
            JSONObject json = getPermissionJsonObject(permission);

            if (parentJson == null && oConvertUtils.isEmpty(tempPid)) {
                // 根节点，直接加入结果集合
                jsonArray.add(json);

                // 非叶子节点递归查找子节点
                if (!permission.isLeaf()) {
                    getPermissionJsonArray(jsonArray, metaList, json);
                }
            } else if (parentJson != null && oConvertUtils.isNotEmpty(tempPid)
                    && tempPid.equals(parentJson.getString("id"))) {
                // 非根节点，挂载到父节点

                if (permission.getMenuType() == 0) {
                    // 按钮权限挂载到父节点meta.permissionList
                    JSONObject metaJson = parentJson.getJSONObject("meta");
                    if (metaJson.containsKey("permissionList")) {
                        metaJson.getJSONArray("permissionList").add(json);
                    } else {
                        JSONArray permissionList = new JSONArray();
                        permissionList.add(json);
                        metaJson.put("permissionList", permissionList);
                    }
                } else if (permission.getMenuType() == 1) {
                    // 菜单权限挂载到父节点children
                    if (parentJson.containsKey("children")) {
                        parentJson.getJSONArray("children").add(json);
                    } else {
                        JSONArray children = new JSONArray();
                        children.add(json);
                        parentJson.put("children", children);
                    }

                    // 递归处理非叶子菜单的子菜单
                    if (!permission.isLeaf()) {
                        getPermissionJsonArray(jsonArray, metaList, json);
                    }
                }
            }
        }
    }

    /**
     * 将权限实体转换为对应的JSON对象
     *
     * @param permission 权限实体
     * @return JSON格式权限节点
     */
    private JSONObject getPermissionJsonObject(SysPermission permission) {
        JSONObject json = new JSONObject();

        // 菜单类型：0一级菜单，1子菜单，2按钮
        if (permission.getMenuType() == 2) {
            // 按钮权限
            json.put("action", permission.getPerms());
            json.put("describe", permission.getName());
        } else if (permission.getMenuType() == 0 || permission.getMenuType() == 1) {
            // 菜单权限
            json.put("id", permission.getId());

            // 对外链URL进行Base64编码，避免路由冲突
            if (permission.getUrl() != null
                    && (permission.getUrl().startsWith("http://") || permission.getUrl().startsWith("https://"))) {
                String url = new String(Base64.getUrlEncoder().encode(permission.getUrl().getBytes()));
                json.put("path", "/sys/link/" + url.replaceAll("=", ""));
            } else {
                json.put("path", permission.getUrl());
            }

            String urlStr = permission.getUrl();
            if (oConvertUtils.isNotEmpty(urlStr)) {
                if (urlStr.startsWith("/")) {
                    urlStr = urlStr.substring(1);
                }
                // 设置菜单名称，路径中斜杠替换成短横线
                json.put("name", urlStr.replace("/", "-"));
            } else {
                json.put("name", "");
            }

            // 是否隐藏路由，默认显示
            if (permission.isHidden()) {
                json.put("hidden", true);
            }
            // 是否聚合显示路由（alwaysShow）
            if (permission.isAlwaysShow()) {
                json.put("alwaysShow", true);
            }

            json.put("component", permission.getComponent());

            // 元信息
            JSONObject meta = new JSONObject();
            meta.put("title", permission.getName());

            // 一级菜单添加重定向地址和图标
            if (oConvertUtils.isEmpty(permission.getParentId())) {
                json.put("redirect", permission.getRedirect());
                meta.put("icon", oConvertUtils.getString(permission.getIcon(), ""));
            } else {
                meta.put("icon", oConvertUtils.getString(permission.getIcon(), ""));
            }

            // 外链URL设置在meta.url字段
            if (permission.getUrl() != null
                    && (permission.getUrl().startsWith("http://") || permission.getUrl().startsWith("https://"))) {
                meta.put("url", permission.getUrl());
            }

            json.put("meta", meta);
        }

        return json;
    }
}

